package edu.zju.gis.cky.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import edu.zju.gis.cky.cons.Constant;
import edu.zju.gis.cky.dao.ChangeGeomMapper;
import edu.zju.gis.cky.dao.FlowGeomMapper;
import edu.zju.gis.cky.dao.MetaMapper;
import edu.zju.gis.cky.entity.Meta;
import edu.zju.gis.cky.entity.dto.ChangeMatrixDTO;
import edu.zju.gis.cky.entity.dto.StatisticAreaByOneClassDTO;
import edu.zju.gis.cky.entity.po.AreaStatisticPO;
import edu.zju.gis.cky.entity.po.FlowGeomPO;
import edu.zju.gis.cky.entity.po.StatisticPO;
import edu.zju.gis.cky.service.LandFlow2Service;
import org.geotools.data.DataUtilities;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKTReader;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import static edu.zju.gis.cky.cons.Constant.CLASS_TO_NAME;


@Service
public class LandFlow2ServiceImpl implements LandFlow2Service {

    @Autowired
    private MetaMapper metaMapper;
    @Autowired
    private ChangeGeomMapper changeGeomMapper;

    @Override
    public String[][] getTable(ChangeMatrixDTO changeMatrixDTO) {
        Meta metaBegin = metaMapper.selectByPrimaryKey(changeMatrixDTO.getBeginMetaId());
        Meta metaEnd = metaMapper.selectByPrimaryKey(changeMatrixDTO.getEndMetaId());
        String tableName = Constant.MODEL_SCHEMA + ".geom_" + metaBegin.getPgStorage() + "_" + metaEnd.getPgStorage();
        int type = changeMatrixDTO.getType();

        List<String> fromList = null;
        List<String> toList = null;
        List<String> oneFromList = new ArrayList<String>();
        List<String> oneToList = null;
        if (changeMatrixDTO.getFrom() != null) {
            fromList = Arrays.asList(changeMatrixDTO.getFrom().split(","));
        }

        //oneFromList、oneToList记录二级编码
        for (String e : fromList) {
            String[] temp = type == 1 ? Constant.ONE_TO_TWO.get(e) : Constant.THREE_TO_TWO.get(e);
            oneFromList.addAll(Arrays.asList(temp));
        }
        if (changeMatrixDTO.getTo() != null) {
            oneToList = new ArrayList<>();
            toList = Arrays.asList(changeMatrixDTO.getTo().split(","));
            for (String e : toList) {
                String[] temp = type == 1 ? Constant.ONE_TO_TWO.get(e) : Constant.THREE_TO_TWO.get(e);
                oneToList.addAll(Arrays.asList(temp));
            }
        }
        List<FlowGeomPO> geomPOS = changeGeomMapper.getSelective(tableName, oneFromList, oneToList);

        //变化矩阵初始化
        int maxrow = 0;
        int maxcol = 0;
        if (changeMatrixDTO.getTo() != null) {
            maxrow = oneFromList.size() + 3;
            maxcol = oneToList.size() + 3;
        } else {
            if (changeMatrixDTO.getType() == 1) {
                maxrow = oneFromList.size() + 3;
                maxcol = 13 + 3;
            } else {
                maxrow = oneFromList.size() + 3;
                maxcol = 3 + 3;
            }
        }
        String[][] changeMatrix = new String[maxrow][maxcol];
        for (int i = 0; i < maxrow; i++) {
            changeMatrix[i][0] = "";
            changeMatrix[i][1] = "";
        }
        for (int i = 0; i < maxcol; i++) {
            changeMatrix[0][i] = "";
            changeMatrix[1][i] = "";
        }
        for (int i = 2; i < maxrow; i++) {
            for (int j = 2; j < maxcol; j++) {
                changeMatrix[i][j] = "0";
            }
        }
        changeMatrix[0][0] = "2019/2020";
        changeMatrix[maxrow - 1][1] = "总计";
        changeMatrix[1][maxcol - 1] = "总计";

        //保存位置记录
        HashMap<String, Integer> row = new HashMap<>();
        HashMap<String, Integer> column = new HashMap<>();
        for (int i = 0; i < oneFromList.size(); i++) {
            changeMatrix[i + 2][0] = oneFromList.get(i);
            String temp = oneFromList.get(i);
            if (temp.contains("K")) {
                temp = oneFromList.get(i).substring(0, 4);
            }
            changeMatrix[i + 2][1] = CLASS_TO_NAME.get(temp);
            row.put(oneFromList.get(i), i + 2);
        }


        //to不为空，列为二级编码；to为空，列展示一级编码
        if (changeMatrixDTO.getTo() != null) {
            for (int i = 0; i < oneToList.size(); i++) {
                changeMatrix[0][i + 2] = oneToList.get(i);
                String temp = oneToList.get(i);
                changeMatrix[1][i + 2] = Constant.CLASS_TO_NAME.get(temp);
                column.put(oneToList.get(i), i + 2);
            }

            for (FlowGeomPO flowGeoPo : geomPOS) {
                Integer rowIndex = row.get(flowGeoPo.getDlbmFrom());
                Integer colIndex = column.get(flowGeoPo.getDlbmTo());
                if (rowIndex != null && colIndex != null) {
                    changeMatrix[rowIndex][colIndex] = String.valueOf(flowGeoPo.getArea());
                    changeMatrix[rowIndex][maxcol - 1] = String.valueOf(Double.parseDouble(changeMatrix[rowIndex][maxcol - 1]) + flowGeoPo.getArea());
                    changeMatrix[maxrow - 1][colIndex] = String.valueOf(Double.parseDouble(changeMatrix[maxrow - 1][colIndex]) + flowGeoPo.getArea());
                }
            }

        } else {
            if (changeMatrixDTO.getType() == 1) {
                for (int i = 0; i < 13; i++) {
                    changeMatrix[0][i + 2] = Constant.ONE_CLASS_NUMBER[i];
                    changeMatrix[1][i + 2] = Constant.ONE_CLASS.get(Constant.ONE_CLASS_NUMBER[i]);
                    column.put(Constant.ONE_CLASS_NUMBER[i], i + 2);
                }
                geomPOS = changeGeomMapper.getSelective(tableName, oneFromList, oneToList);
                for (FlowGeomPO flowGeoPo : geomPOS) {
                    Integer rowIndex = row.get(flowGeoPo.getDlbmFrom());
                    String oneClass = flowGeoPo.getDlbmTo();
                    Integer colIndex = column.get(Constant.TWO_TO_ONE.get(oneClass));
                    if (rowIndex != null && colIndex != null) {
                        changeMatrix[rowIndex][colIndex] = String.valueOf(Double.parseDouble(changeMatrix[rowIndex][colIndex]) + flowGeoPo.getArea());
                        changeMatrix[rowIndex][maxcol - 1] = String.valueOf(Double.parseDouble(changeMatrix[rowIndex][maxcol - 1]) + flowGeoPo.getArea());
                        changeMatrix[maxrow - 1][colIndex] = String.valueOf(Double.parseDouble(changeMatrix[maxrow - 1][colIndex]) + flowGeoPo.getArea());
                    }
                }
            } else {
                for (int i = 0; i < 3; i++) {
                    changeMatrix[0][i + 2] = Constant.THREE_CLASS_NUMBER[i];
                    changeMatrix[1][i + 2] = Constant.THREE_CLASS_NAME[i];
                    column.put(Constant.THREE_CLASS_NAME[i], i + 2);
                }
                for (FlowGeomPO flowGeoPo : geomPOS) {
                    Integer rowIndex = row.get(flowGeoPo.getDlbmFrom());
                    String oneClass = flowGeoPo.getDlbmTo();
                    Integer colIndex = column.get(Constant.THREE_TYPE.get(oneClass));
                    if (rowIndex != null && colIndex != null) {
                        changeMatrix[rowIndex][colIndex] = String.valueOf(Double.parseDouble(changeMatrix[rowIndex][colIndex]) + flowGeoPo.getArea());
                        changeMatrix[rowIndex][maxcol - 1] = String.valueOf(Double.parseDouble(changeMatrix[rowIndex][maxcol - 1]) + flowGeoPo.getArea());
                        changeMatrix[maxrow - 1][colIndex] = String.valueOf(Double.parseDouble(changeMatrix[maxrow - 1][colIndex]) + flowGeoPo.getArea());
                    }
                }
            }

        }

        return delK(changeMatrix, 1);
    }

    @Override
    public PageInfo<JSONObject> getList(ChangeMatrixDTO changeMatrixDTO, int pageNum, int pageSize,Double areaFilter) {
        Meta metaBegin = metaMapper.selectByPrimaryKey(changeMatrixDTO.getBeginMetaId());
        Meta metaEnd = metaMapper.selectByPrimaryKey(changeMatrixDTO.getEndMetaId());
        String tableName = Constant.MODEL_SCHEMA + ".geom_" + metaBegin.getPgStorage() + "_" + metaEnd.getPgStorage();
        int type = changeMatrixDTO.getType();

        List<String> fromList = null;
        List<String> toList = null;
        List<String> oneFromList = new ArrayList<>();
        List<String> oneToList = null;
        if (changeMatrixDTO.getFrom() != null) {
            fromList = Arrays.asList(changeMatrixDTO.getFrom().split(","));
        }

        for (String e : fromList) {
            String[] temp = type == 1 ? Constant.ONE_TO_TWO.get(e) : Constant.THREE_TO_TWO.get(e);
            oneFromList.addAll(Arrays.asList(temp));
        }
        if (changeMatrixDTO.getTo() != null) {
            oneToList = new ArrayList<String>();
            toList = Arrays.asList(changeMatrixDTO.getTo().split(","));
            for (String e : toList) {
                String[] temp = type == 1 ? Constant.ONE_TO_TWO.get(e) : Constant.THREE_TO_TWO.get(e);
                oneToList.addAll(Arrays.asList(temp));
            }
        }
        PageHelper.startPage(pageNum, pageSize);
        List<FlowGeomPO> geomPOS = changeGeomMapper.getSelectiveFilter(tableName, oneFromList, oneToList,areaFilter);
        List<FlowGeomPO> geomAll = changeGeomMapper.getSelectiveFilter(tableName, oneFromList, oneToList,areaFilter);
        PageInfo<JSONObject> result = new PageInfo<>(transPO2GeoJson(geomPOS, changeMatrixDTO.getType()));
        result.setTotal(geomAll.size());
        return result;
    }

    private List<JSONObject> transPO2GeoJson(List<FlowGeomPO> detailSelective, Integer typeClass) {
        List<JSONObject> result = new ArrayList<>();
        for (FlowGeomPO changeGeomPO : detailSelective) {
            String wkt = changeGeomPO.getWKT();
            WKTReader reader = new WKTReader();
            try {
                Geometry geometry = reader.read(wkt);
                String typeSpec = "geometry:" + geometry.getGeometryType() + "," + changeGeomPO.getTypeSpec() + ",oneClassDlbmFrom,oneClassDlmcFrom";
                SimpleFeatureType type = DataUtilities.createType("geom", typeSpec);
                SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
                String dlbmFrom = changeGeomPO.getDlbmFrom();
                if (changeGeomPO.getDlbmFrom().contains("K")) {
                    dlbmFrom = Constant.K_UP.get(changeGeomPO.getDlbmFrom());
                }
                featureBuilder.set("dlbmFrom", dlbmFrom);
                featureBuilder.set("dlmcFrom", changeGeomPO.getDlmcFrom());

                if (typeClass != null && typeClass == 1) {
                    featureBuilder.set("dlmcTo", Constant.TWO_TO_ONE.get(changeGeomPO.getDlbmTo()));
                    featureBuilder.set("dlbmTo", Constant.ONE_CLASS.get(Constant.TWO_TO_ONE.get(changeGeomPO.getDlmcTo())));
                } else {
                    featureBuilder.set("dlmcTo", Constant.THREE_TYPE.get(changeGeomPO.getDlbmTo()));
                    featureBuilder.set("dlbmTo", Constant.TWO_TO_ONE.get(changeGeomPO.getDlbmTo()));
                }

                if (typeClass != null) {
                    if (typeClass == 1) {
                        String oneClassNameFrom = Constant.TWO_TO_ONE.get(changeGeomPO.getDlbmFrom());
                        featureBuilder.set("oneClassDlbmFrom", oneClassNameFrom);
                        featureBuilder.set("oneClassDlmcFrom", Constant.ONE_CLASS.get(oneClassNameFrom));
                    } else if (typeClass == 2) {
                        String oneClassNameFrom = Constant.THREE_TYPE.get(changeGeomPO.getDlbmFrom());
                        featureBuilder.set("oneClassDlmcFrom", oneClassNameFrom);
                        featureBuilder.set("oneClassDlbmFrom", Constant.THREE_TYPE_NAME.get(oneClassNameFrom));
                    }
                }
                featureBuilder.set("area", changeGeomPO.getArea());
                featureBuilder.add(geometry);
                SimpleFeature feature = featureBuilder.buildFeature(changeGeomPO.getFid());
                StringWriter writer = new StringWriter();
                FeatureJSON fJson = new FeatureJSON();
                fJson.writeFeature(feature, writer);
                String geoJsonResult = writer.toString();
                JSONObject jsonObject = JSONObject.parseObject(geoJsonResult);
                result.add(jsonObject);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    @Override
    public JSONObject statistic(ChangeMatrixDTO changeMatrixDTO) {
        Meta metaBegin = metaMapper.selectByPrimaryKey(changeMatrixDTO.getBeginMetaId());
        Meta metaEnd = metaMapper.selectByPrimaryKey(changeMatrixDTO.getEndMetaId());
        String tableNameFrom = Constant.VECTOR_SCHEMA + "." + metaBegin.getPgStorage();
        String tableNameTo = Constant.VECTOR_SCHEMA + "." + metaEnd.getPgStorage();
        String tableNameChange = Constant.MODEL_SCHEMA + ".geom_" + metaBegin.getPgStorage() + "_" + metaEnd.getPgStorage();
        int type = changeMatrixDTO.getType();

        List<String> fromList = null;
        List<String> toList = null;
        ArrayList<String> oneFromList = new ArrayList<String>();
        ArrayList<String> oneToList = new ArrayList<String>();
        if (changeMatrixDTO.getFrom() != null) {
            fromList = Arrays.asList(changeMatrixDTO.getFrom().split(","));
        }
        if (changeMatrixDTO.getTo() == null) {
            String[] temp = type == 1 ? Constant.ONE_CLASS_NUMBER : Constant.THREE_CLASS_NUMBER;
            toList = Arrays.asList(temp);
        } else {
            toList = Arrays.asList(changeMatrixDTO.getTo().split(","));
        }
        //oneFromList、oneToList记录二级编码
        for (String e : toList) {
            String[] temp;
            temp = type == 1 ? Constant.ONE_TO_TWO.get(e) : Constant.THREE_TO_TWO.get(e);
            oneToList.addAll(Arrays.asList(temp));
        }
        for (String e : fromList) {
            String[] temp;
            temp = type == 1 ? Constant.ONE_TO_TWO.get(e) : Constant.THREE_TO_TWO.get(e);
            oneFromList.addAll(Arrays.asList(temp));
        }

        List<FlowGeomPO> geomPOSTempOut = changeGeomMapper.getSelective(tableNameChange, oneFromList, oneToList);
        List<FlowGeomPO> geomPOSTempIn = changeGeomMapper.getSelective(tableNameChange, oneToList, oneFromList);
        List<StatisticPO> rawGeoSumFrom = changeGeomMapper.getSumAreaTo(tableNameTo);
        List<StatisticPO> geoSumFrom = new ArrayList<>();
        for (StatisticPO value : rawGeoSumFrom) {
            if (oneFromList.contains(value.getDlbm())) {
                if (!value.getDlbm().contains("K")) {
                    StatisticPO statisticPO = new StatisticPO(value.getDlbm(), value.getShapeArea());
                    geoSumFrom.add(statisticPO);
                } else {
                    boolean flag = false;
                    for (StatisticPO po : geoSumFrom) {
                        if (po.getDlbm().equals(Constant.K_UP.get(value.getDlbm()))) {
                            po.setShapeArea(po.getShapeArea() + value.getShapeArea());
                            flag = true;
                        }
                    }
                    if (!flag) {
                        StatisticPO statisticPO = new StatisticPO(value.getDlbm(), value.getShapeArea());
                        geoSumFrom.add(statisticPO);
                    }
                }
            }
        }

        List<StatisticPO> rawGeoSumTo = changeGeomMapper.getSumAreaTo(tableNameTo);
        List<StatisticPO> geoSumTo = new ArrayList<>();
        for (StatisticPO value : rawGeoSumTo) {
            if (oneToList.contains(value.getDlbm())) {
                if (!value.getDlbm().contains("K")) {
                    StatisticPO statisticPO = new StatisticPO(value.getDlbm(), value.getShapeArea());
                    geoSumTo.add(statisticPO);
                } else {
                    boolean flag = false;
                    for (StatisticPO po : geoSumTo) {
                        if (po.getDlbm().equals(Constant.K_UP.get(value.getDlbm()))) {
                            po.setShapeArea(po.getShapeArea() + value.getShapeArea());
                            flag = true;
                        }
                    }
                    if (!flag) {
                        StatisticPO statisticPO = new StatisticPO(value.getDlbm(), value.getShapeArea());
                        geoSumTo.add(statisticPO);
                    }
                }
            }
        }

        //记录
        HashMap<String, Integer> sumFromCol = new HashMap<String, Integer>();
        HashMap<String, Integer> sumToCol = new HashMap<String, Integer>();
        for (int i = 0; i < geoSumFrom.size(); i++) {
            sumFromCol.put(geoSumFrom.get(i).getDlbm(), i);
        }
        for (int i = 0; i < geoSumTo.size(); i++) {
            sumToCol.put(geoSumTo.get(i).getDlbm(), i);
        }

        HashMap<String, StatisticPO[]> geomOutResult = null;
        HashMap<String, StatisticPO[]> geomInResult = null;
        try {
            geomOutResult = addByOneClass(geomPOSTempOut, type, oneFromList, toList, "out");
            geomInResult = addByOneClass(geomPOSTempIn, type, oneFromList, toList, "in");
        } catch (Exception e) {
            e.printStackTrace();
        }

        //结果矩阵初始化
        String[][] scaleOut = null;
        String[][] scaleIn = null;
        scaleOut = new String[oneFromList.size() + 1][oneToList.size() + 1];
        scaleIn = new String[oneFromList.size() + 1][oneToList.size() + 1];
        scaleIn[0][0] = "from/to";
        scaleOut[0][0] = "from/to";
        HashMap<String, Integer> rowOutcolIn = new HashMap<>();
        HashMap<String, Integer> colOutrowIn = new HashMap<>();
        for (int i = 0; i < oneFromList.size(); i++) {
            scaleOut[i + 1][0] = oneFromList.get(i);
            scaleIn[i + 1][0] = oneFromList.get(i);
            rowOutcolIn.put(oneFromList.get(i), i + 1);
        }
        for (int i = 0; i < oneToList.size(); i++) {
            scaleOut[0][i + 1] = oneToList.get(i);
            scaleIn[0][i + 1] = oneToList.get(i);
            colOutrowIn.put(oneToList.get(i), i + 1);
        }
        for (int i = 1; i < oneFromList.size() + 1; i++) {
            for (int j = 1; j < oneToList.size() + 1; j++) {
                scaleOut[i][j] = String.valueOf(0.0);
                scaleIn[i][j] = String.valueOf(0.0);
            }
        }

        //如果to不为空，计算每个二级类流入流出占总的一级类流入流出的比例
        for (FlowGeomPO data : geomPOSTempOut) {
            int rowOut = rowOutcolIn.get(data.getDlbmFrom());
            int colOut = colOutrowIn.get(data.getDlbmTo());
            String toOneClass;
            if (type == 1) {
                toOneClass = Constant.TWO_TO_ONE.get(data.getDlbmTo());
            } else {
                toOneClass = Constant.THREE_TYPE_NAME.get(Constant.THREE_TYPE.get(data.getDlbmTo()));
            }
            int index = sumFromCol.get(data.getDlbmFrom());
            Double oneClassAreaOut = geoSumFrom.get(index).getShapeArea();
            scaleOut[rowOut][colOut] = String.valueOf(data.getArea() / oneClassAreaOut);
        }

        for (FlowGeomPO data : geomPOSTempIn) {
            int rowOut = 0;
            int colOut = 0;
            rowOut = colOutrowIn.get(data.getDlbmFrom());
            colOut = rowOutcolIn.get(data.getDlbmTo());
            String toOneClass;
            if (type == 1) {
                toOneClass = Constant.TWO_TO_ONE.get(data.getDlbmFrom());
            } else {
                toOneClass = Constant.THREE_TYPE_NAME.get(Constant.THREE_TYPE.get(data.getDlbmFrom()));
            }
            int index = sumToCol.get(data.getDlbmFrom());
            Double oneClassAreaIn = geoSumTo.get(index).getShapeArea();
            scaleIn[colOut][rowOut] = String.valueOf(data.getArea() / oneClassAreaIn);
        }

        List<StatisticPO> changeOut = changeGeomMapper.getChangeSumArea(tableNameChange, oneFromList);
        List<StatisticPO> changeIn = changeGeomMapper.getChangeSumArea(tableNameChange, oneToList);

        JSONObject result = new JSONObject();
        JSONObject jsonObject1 = new JSONObject();
        JSONObject jsonObject2 = new JSONObject();

        //统计一级类面积现状
        List<StatisticPO> geoSumNullTo = new ArrayList<StatisticPO>() {{
            String[] oneClass = Constant.ONE_CLASS_NUMBER;
            String[] threeClass = Constant.THREE_CLASS_NUMBER;
            for (int i = 0; i < (type == 1 ? oneClass.length : threeClass.length); i++) {
                add(new StatisticPO(type == 1 ? oneClass[i] : threeClass[i], 0.0));
            }
        }};
        if (changeMatrixDTO.getTo() == null) {
            for (StatisticPO data : geoSumTo) {
                String dlbm = data.getDlbm();
                String oneIndex = type == 1 ? Constant.TWO_TO_ONE.get(dlbm) : Constant.THREE_TYPE_NAME.get(Constant.THREE_TYPE.get(dlbm));
                int number = type == 1 ? Integer.parseInt(oneIndex) : Integer.parseInt(oneIndex) - 1;
                Double area = geoSumNullTo.get(number).getShapeArea();
                geoSumNullTo.get(number).setShapeArea(area + data.getShapeArea());
            }
        }

        List<StatisticPO> geoChangeSumNullTo = new ArrayList<StatisticPO>() {{
            String[] oneClass = Constant.ONE_CLASS_NUMBER;
            String[] threeClass = Constant.THREE_CLASS_NUMBER;
            for (int i = 0; i < (type == 1 ? oneClass.length : threeClass.length); i++) {
                add(new StatisticPO(type == 1 ? oneClass[i] : threeClass[i], 0.0));
            }
        }};

        if (changeMatrixDTO.getTo() == null) {
            for (StatisticPO data : changeOut) {
                String dlbm = data.getDlbm();
                String oneIndex = type == 1 ? Constant.TWO_TO_ONE.get(dlbm) : Constant.THREE_TYPE_NAME.get(Constant.THREE_TYPE.get(dlbm));
                int number = type == 1 ? Integer.parseInt(oneIndex) : Integer.parseInt(oneIndex) - 1;
                Double area = geoChangeSumNullTo.get(number).getShapeArea();
                geoChangeSumNullTo.get(number).setShapeArea(area + data.getShapeArea());
            }
        }

//        jsonObject1.put("fromTypeSecondCode", oneFromList);
//        jsonObject1.put("outflowAreaProportion", delK(scaleOut, 2));
        jsonObject1.put("fromArea", geoSumFrom);
        jsonObject1.put("fromChangeArea", changeOut);
        result.put("outflow", jsonObject1);
//        jsonObject2.put("toTypeSecondCode", toList);
//        jsonObject2.put("inflowAreaProportion", delK(scaleIn, 2));
        jsonObject2.put("toArea", changeMatrixDTO.getTo() == null ? geoSumNullTo : geoSumTo);
        jsonObject2.put("toChangeArea", changeMatrixDTO.getTo() == null ? geoChangeSumNullTo : changeOut);
        result.put("inflow", jsonObject2);
        return result;
    }

    @Override
    public HashMap<String, String[][]> getAreaByXZQH(StatisticAreaByOneClassDTO dto) {
        Long beginid = dto.getBeginMetaId();
        Long endid = dto.getEndMetaId();
        int type = dto.getType();
        Meta metaBegin = metaMapper.selectByPrimaryKey(dto.getBeginMetaId());
        Meta metaEnd = metaMapper.selectByPrimaryKey(dto.getEndMetaId());
        String tableNameBegin = Constant.VECTOR_SCHEMA + "." + metaBegin.getPgStorage();
        String tableNameEnd = Constant.VECTOR_SCHEMA + "." + metaEnd.getPgStorage();
        String xzqh = dto.getXzqh();
        String list = dto.getCode();
        Integer xzqhIndex = 0;


        List<String> oneClass = new ArrayList<String>();
        HashMap<String, List<String>> twoClass = new HashMap<String, List<String>>();
        List<String> xzqhList = new ArrayList<String>();

        if (list != null) {
            oneClass = Arrays.asList(list.split(","));
        } else {
            String[] oneClassArray = Constant.ONE_CLASS_NUMBER;
            String[] threeClassArray = Constant.THREE_CLASS_NUMBER;
            oneClass.addAll(Arrays.asList(type == 1 ? oneClassArray : threeClassArray));
        }
        for (String data : oneClass) {
            String[] temp = type == 1 ? Constant.ONE_TO_TWO.get(data) : Constant.THREE_TO_TWO.get(data);
            List<String> twoClassList = new ArrayList<String>();
            twoClassList.addAll(Arrays.asList(temp));
            twoClass.put(data, twoClassList);
        }
        if (xzqh != null) {
            xzqhList.addAll(Arrays.asList(xzqh.split(",")));
        }

        Integer sumIndex = 0;
        xzqhIndex = xzqhList.get(0).length();
        switch (xzqhIndex) {
            case 4:
                sumIndex = xzqhIndex + 2;
                break;
            case 6:
                sumIndex = xzqhIndex + 3;
                break;
            case 9:
                sumIndex = xzqhIndex + 3;
                break;
            default:
                sumIndex = 0;
        }

        HashMap<String, List<AreaStatisticPO>> beginResult = new HashMap<String, List<AreaStatisticPO>>();
        HashMap<String, List<AreaStatisticPO>> endResult = new HashMap<String, List<AreaStatisticPO>>();
        for (String data : oneClass) {
            List<AreaStatisticPO> begin = changeGeomMapper.getAreaSumByXZQH(tableNameBegin, twoClass.get(data), xzqhList, xzqhIndex,sumIndex);
            List<AreaStatisticPO> end = changeGeomMapper.getAreaSumByXZQH(tableNameEnd, twoClass.get(data), xzqhList, xzqhIndex,sumIndex);
            beginResult.put(data, begin);
            endResult.put(data, end);
        }

        HashMap<String, String[][]> result = new HashMap<String, String[][]>();
        for (String data : oneClass) {
            int col = (int) (endid - beginid + 2);
            String[][] areaResult = new String[beginResult.get(data).size() + 1][col];
            areaResult[0][0] = "行政区划代码";
            areaResult[0][1] = metaBegin.getPgStorage();
            areaResult[0][2] = metaEnd.getPgStorage();
            for (int i = 0; i < beginResult.get(data).size(); i++) {
                List<AreaStatisticPO> areabegin = beginResult.get(data);
                List<AreaStatisticPO> areaend = endResult.get(data);
                areaResult[i + 1][0] = areabegin.get(i).getZldwdm();
                areaResult[i + 1][1] = String.valueOf(areabegin.get(i).getArea());
                areaResult[i + 1][2] = String.valueOf(areaend.get(i).getArea());
            }
            result.put(data, areaResult);
        }
        return result;
    }

    public HashMap<String, StatisticPO[]> addByOneClass(List<FlowGeomPO> data, int type, List<String> from, List<String> to, String direction) {
        //将数据库二级类结果统计为一级类
        HashMap<String, StatisticPO[]> oneClassStatResult;
        oneClassStatResult = new HashMap<String, StatisticPO[]>() {{
            for (String e : from) {
                put(e, new StatisticPO[to.size()]);
            }
        }};
        for (String e : from) {
            for (int i = 0; i < to.size(); i++) {
                oneClassStatResult.get(e)[i] = new StatisticPO();
                StatisticPO temp = oneClassStatResult.get(e)[i];
                oneClassStatResult.get(e)[i].setDlbm(to.get(i));
                oneClassStatResult.get(e)[i].setShapeArea(0.0);
            }
        }
        if (type == 1) {
            for (FlowGeomPO statistic : data) {
                if (direction.equals("out")) {
                    String fromNumber = statistic.getDlbmFrom();
                    String oneClass = Constant.TWO_TO_ONE.get(statistic.getDlbmTo());
                    if (statistic.getDlbmTo().length() > 4) {
                        oneClass = Constant.TWO_TO_ONE.get(statistic.getDlbmTo().substring(0, 4));
                    }

                    for (int i = 0; i < to.size(); i++) {
                        if (to.get(i).equals(oneClass)) {
                            double area = oneClassStatResult.get(fromNumber)[i].getShapeArea();
                            oneClassStatResult.get(fromNumber)[i].setShapeArea(area + statistic.getArea());
                        }
                    }
                } else {
                    String toNumber = statistic.getDlbmTo();
                    String oneClass = Constant.TWO_TO_ONE.get(statistic.getDlbmFrom());
                    if (statistic.getDlbmFrom().length() > 4) {
                        oneClass = Constant.TWO_TO_ONE.get(statistic.getDlbmFrom().substring(0, 4));
                    }

                    for (int i = 0; i < to.size(); i++) {
                        if (to.get(i).equals(oneClass)) {
                            double area = oneClassStatResult.get(toNumber)[i].getShapeArea();
                            oneClassStatResult.get(toNumber)[i].setShapeArea(area + statistic.getArea());
                        }
                    }

                }
            }
        } else {
            for (FlowGeomPO statistic : data) {
                if (direction.equals("out")) {
                    String fromNumber = statistic.getDlbmFrom();
                    String oneClass = Constant.THREE_TYPE_NAME.get(Constant.THREE_TYPE.get(statistic.getDlbmTo()));
                    if (statistic.getDlbmTo().length() > 4) {
                        oneClass = Constant.THREE_TYPE_NAME.get(Constant.THREE_TYPE.get(statistic.getDlbmTo().substring(0, 4)));
                    }

                    for (int i = 0; i < to.size(); i++) {
                        if (to.get(i).equals(oneClass)) {
                            double area = oneClassStatResult.get(fromNumber)[i].getShapeArea();
                            oneClassStatResult.get(fromNumber)[i].setShapeArea(area + statistic.getArea());
                        }
                    }
                } else {
                    String toNumber = statistic.getDlbmTo();
                    String oneClass = Constant.THREE_TYPE_NAME.get(Constant.THREE_TYPE.get(statistic.getDlbmFrom()));
                    if (statistic.getDlbmFrom().length() > 4) {
                        oneClass = Constant.THREE_TYPE_NAME.get(Constant.THREE_TYPE.get(statistic.getDlbmFrom().substring(0, 4)));
                    }

                    for (int i = 0; i < to.size(); i++) {
                        if (to.get(i).equals(oneClass)) {
                            double area = oneClassStatResult.get(toNumber)[i].getShapeArea();
                            oneClassStatResult.get(toNumber)[i].setShapeArea(area + statistic.getArea());
                        }
                    }

                }
            }
        }
        return oneClassStatResult;
    }

    public String[][] delK(String[][] data, int type) {
        //将包含K的二级编码合并
        for (int i = 0; i < data.length; i++) {
            if (data[i][0].contains("K")) {
                data[i][0] = Constant.K_UP.get(data[i][0]);
            }
        }
        for (int i = 0; i < data[0].length; i++) {
            if (data[0][i].contains("K")) {
                data[0][i] = Constant.K_UP.get(data[0][i]);
            }
        }
        for (int i = type == 1 ? 2 : 1; i < (type == 1 ? data.length - 1 : data.length); i++) {
            String temp = data[i][0];
            if (temp.equals("Del")) {
                continue;
            }
            for (int j = i + 1; j < data.length; j++) {
                if (data[j][0].equals(temp)) {
                    data[j][0] = "Del";
                    for (int k = type == 1 ? 2 : 1; k < (type == 1 ? data[0].length - 1 : data[0].length); k++) {
                        data[i][k] = String.valueOf(Double.parseDouble(data[j][k]) + Double.parseDouble(data[i][k]));
                        data[j][k] = "0";
                    }
                }
            }
        }
        for (int i = type == 1 ? 2 : 1; i < (type == 1 ? data[0].length - 1 : data[0].length); i++) {
            String temp = data[0][i];
            if (temp.equals("Del")) {
                continue;
            }
            for (int j = i + 1; j < data[0].length; j++) {
                if (data[0][j].equals(temp)) {
                    data[0][j] = "Del";
                    for (int k = type == 1 ? 2 : 1; k < (type == 1 ? data.length - 1 : data.length); k++) {
                        data[k][i] = String.valueOf(Double.parseDouble(data[k][j]) + Double.parseDouble(data[k][i]));
                        data[k][j] = "0";
                    }
                }
            }
        }

        int delRow = 0;
        int delCol = 0;
        for (String[] row : data) {
            if (row[0].equals("Del")) {
                delRow++;
            }
        }
        for (String col : data[0]) {
            if (col.equals("Del")) {
                delCol++;
            }
        }
        String[][] newData1 = new String[data.length - delRow][data[0].length];
        int currentRow = 0;
        for (String[] row : data) {
            if (!row[0].equals("Del")) {
                for (int j = 0; j < data[0].length; j++) {
                    newData1[currentRow][j] = row[j];
                }
                currentRow++;
            }
        }
        String[][] newData2 = new String[data.length - delRow][data[0].length - delCol];
        int currentCol = 0;
        for (int i = 0; i < newData1[0].length; i++) {
            if (!newData1[0][i].equals("Del")) {
                for (int j = 0; j < newData1.length; j++) {
                    newData2[j][currentCol] = newData1[j][i];
                }
                currentCol++;
            }
        }
        return newData2;
    }
}
